using System;

namespace Cesium3DTilesSelection
{
    public class TileSelectionState
    {
        /**
  * @brief Enumeration of possible results of a {@link TileSelectionState}
  */
        public enum Result
        {
            /**
             * @brief There was no selection result.
             *
             * This may be the case when the tile wasn't visited last frame.
             */
            None = 0,

            /**
             * @brief This tile was deemed not visible and culled.
             */
            Culled = 1,

            /**
             * @brief The tile was selected for rendering.
             */
            Rendered = 2,

            /**
             * @brief This tile did not meet the required screen-space error and was
             * refined.
             */
            Refined = 3,

            /**
             * @brief This tile was rendered but then removed from the render list
             *
             * This tile was originally rendered, but it got kicked out of the render
             * list in favor of an ancestor because it is not yet renderable.
             */
            RenderedAndKicked = 4,

            /**
             * @brief This tile was refined but then removed from the render list
             *
             * This tile was originally refined, but its rendered descendants got kicked
             * out of the render list in favor of an ancestor because it is not yet
             * renderable.
             */
            RefinedAndKicked = 5
        }
        public int FrameNumber { get; set; }
        public Result pResult { get; set; }

        public TileSelectionState(int frameNumber = 0, Result result = Result.None)
        {
            this.FrameNumber = frameNumber;
            this.pResult = result;
        }

        internal Result getResult(int frameNumber)
        {
            if (this.FrameNumber != frameNumber)
            {
                return Result.None;
            }
            return this.pResult;
        }

        public bool wasKicked(int frameNumber)
        {
            Result result = this.getResult(frameNumber);
            return result == Result.RenderedAndKicked || result == Result.RefinedAndKicked;
        }

        internal void kick()
        {
            switch (this.pResult)
            {
                case Result.Rendered:
                    this.pResult = Result.RenderedAndKicked;
                    break;
                case Result.Refined:
                    this.pResult = Result.RefinedAndKicked;
                    break;
                default:
                    break;
            }
        }

        internal Result getOriginalResult(int frameNumber)
        {
            Result result = this.getResult(frameNumber);
            switch (result)
            {
                case Result.RefinedAndKicked:
                    return Result.Refined;
                case Result.RenderedAndKicked:
                    return Result.Rendered;
                default:
                    return result;
            }
        }
    }
}